//
//  EnemyFighterSprite.cpp
//  airfight
//
//  Created by USER on 12-9-13.
//  Copyright (c) 2012年 moonriver. All rights reserved.
//

#include "EnemyFighterSprite.h"
#include "BattleActionLayer.h"

EnemyFighterSprite::EnemyFighterSprite(PlayerFighterSprite *p_playerFighter)
: m_pFighterId(0)
, m_pBlood(0)
, m_pArmor(0)
, m_pIsBoss(0)
, m_iFrameIndex(0)
, m_bBossDestroyed(false)
{
    CC_SAFE_RETAIN(p_playerFighter); 
    m_playerFighter = p_playerFighter;
    bulletFireGroupNumDict = CCDictionary::create();
    bulletFireGroupNumDict->retain();

}

EnemyFighterSprite::~EnemyFighterSprite()
{
    CCLog("delete enemy  = %d",this->getFighterId());
    m_playerFighter->release();
}

bool EnemyFighterSprite::init()
{
    EntitySprite::init();
    
    return true;
}

void EnemyFighterSprite::onEnter()
{
    EntitySprite::onEnter();
    batch = (CCSpriteBatchNode*)getParent();
    m_OldColor = getColor();
    
    Enemy* enemy = EnemyPrototypes::getInstance()->getEnemyByID(m_pFighterId);
    bulletDict = enemy->getBullets();
    CCDictElement* pElement = NULL;
    CCDICT_FOREACH(bulletDict, pElement)
    {
        int bulletid = pElement->getIntKey();
        Bullet *bullet = (Bullet*)pElement->getObject();
        int groupNum = bullet->getGroup_num();
        bulletFireGroupNumDict->setObject(CCInteger::create(groupNum), bulletid);
    }
    //
    scheduleUpdate();
}

EnemyBulletSprite* EnemyFighterSprite::createEnemyBulletSprite(int p_bulletID)
{
    Bullet *createBullet = (Bullet*)bulletDict->valueForKey(p_bulletID);
    EnemyBulletSprite *bulletSprite = new EnemyBulletSprite();
    bulletSprite->retain();
    bulletSprite->init();
    bulletSprite->setPosition(getPosition());
    bulletSprite->setVisible(true);
    bulletSprite->initWithSpriteFrameName(createBullet->getRes().c_str());
    bulletSprite->setDamage(createBullet->getDamage());
    bulletSprite->setEntityType(ENEMY_BULLET);
    m_playerFighter->bullet_idxTag++;
    int bulletTag = this->getTag() * m_playerFighter->bullet_baseTag + m_playerFighter->bullet_idxTag;
    bulletSprite->setTag(bulletTag);
    
    b2BodyDef enemyBulletBodyDef;
    enemyBulletBodyDef.type = b2_dynamicBody;
    enemyBulletBodyDef.position = b2Vec2(getPosition().x/PTM_RATIO, getPosition().y/PTM_RATIO);
    enemyBulletBodyDef.bullet = true;
    enemyBulletBodyDef.userData = bulletSprite;
    b2Body *enemyBulletBody = getPhysicsBody()->GetWorld()->CreateBody(&enemyBulletBodyDef);
    CCSize bulletContentSize = bulletSprite->getContentSize();
    b2PolygonShape playerBulletDynamicBox;
    playerBulletDynamicBox.SetAsBox(bulletContentSize.width * 0.1 / PTM_RATIO, bulletContentSize.height * 0.1 / PTM_RATIO,b2Vec2(0, 0),0);
    b2FixtureDef enemyBulletFixtureDef;
    enemyBulletFixtureDef.shape = &playerBulletDynamicBox;
    enemyBulletFixtureDef.density = 0.0f;
    enemyBulletFixtureDef.friction = 0.0f;
    enemyBulletFixtureDef.filter.groupIndex = FILTER_ENEMY_GROUPINDEX;
    enemyBulletFixtureDef.filter.categoryBits = FILTER_ENEMYBULLET_CATEGORYBITS;
    enemyBulletFixtureDef.filter.maskBits = FILTER_ENEMYBULLET_MASKBITS;
    enemyBulletBody->CreateFixture(&enemyBulletFixtureDef);
    bulletSprite->setPhysicsBody(enemyBulletBody);
    bulletSprite->getPhysicsBody()->SetActive(true);
    return bulletSprite;
}


void EnemyFighterSprite::handleContact(ENTITY_TYPE type, CCDictionary *effect)
{
    if(this->m_pBlood <= 0)
    {
        return;
    }
    switch (type) {
        case PLAYER_BULLET:
        {
            GLubyte Y = 0.299*m_OldColor.r + 0.587*m_OldColor.g + 0.114*m_OldColor.b;
            GLubyte U = -0.147*m_OldColor.r - 0.289*m_OldColor.g + 0.436*m_OldColor.b;
            GLubyte V = 0.615*m_OldColor.r - 0.515*m_OldColor.g - 0.100*m_OldColor.b;
            
            Y = Y - 150 < 0? 0 : Y - 150;
            
            GLubyte R = Y + 1.140*V;
            GLubyte G = Y - 0.394*U - 0.581*V;
            GLubyte B = Y + 2.032*U;
            
            ccColor3B newColor = {R, G, B};
            setColor(newColor);
            
            int damage = ((CCInteger*)effect->objectForKey("damage"))->getValue();
            CCInteger* tag = (CCInteger*)effect->objectForKey("tag");
            this->m_pBlood = (this->m_pBlood - damage) >= 0 ? (this->m_pBlood - damage):0;
            CCNotificationCenter::sharedNotificationCenter()->postNotification(REDRAW_BULLET_CONTACT_NOTIFICATION, tag);
            if(this->m_pBlood <= 0)
            {
                CCInteger* enemyTag = CCInteger::create(this->getTag());
                CCNotificationCenter::sharedNotificationCenter()->postNotification(ENEMY_EXPLOSION_NOTIFICATION, enemyTag);
            }
            
            break;
        } 
        default:
            break;
    }
    
}

void EnemyFighterSprite::update(float dt)
{
    m_iFrameIndex++;
    if (!isVisible())
    {
        return;
    }
    
    if (this->getToDestroyFlag() == ENEMY_DESTROY_BOSS) {
//        b2Body *destroyPlayerBody = this->getPhysicsBody();
//        destroyPlayerBody->SetActive(false);
//        destroyPlayerBody->GetWorld()->DestroyBody(destroyPlayerBody);
        m_OldColor = getColor();
        this->setToDestroyFlag(0);
        m_bBossDestroyed = true;
    }

    if (m_bBossDestroyed)
    {
        if (m_iFrameIndex%21 == 0)
        {
            CCSprite *ani = BattleActionLayer::getInstance()->enemyExplosionAnimation("", 22, 0.02, ccp(getPositionX(), getPositionY() - 30));
            BattleActionLayer::getInstance()->addChild(ani, FIGHTEREXPLOSION_DEPTH);
        }
        else if(m_iFrameIndex%41 == 0)
        {
            CCSprite *ani = BattleActionLayer::getInstance()->enemyExplosionAnimation("", 22, 0.02, ccp(getPositionX() - 35, getPositionY() - 60));
            BattleActionLayer::getInstance()->addChild(ani, FIGHTEREXPLOSION_DEPTH);
        }
        else if(m_iFrameIndex%61 == 0)
        {
            CCSprite *ani = BattleActionLayer::getInstance()->enemyExplosionAnimation("", 22, 0.02, ccp(getPositionX() + 55, getPositionY() - 90));
            BattleActionLayer::getInstance()->addChild(ani, FIGHTEREXPLOSION_DEPTH);
        }
    }
    
    if(this->getToDestroyFlag() != 0)
    {
        this->setVisible(false);
        b2Body *destroyPlayerBody = this->getPhysicsBody();
        destroyPlayerBody->SetActive(false);
        destroyPlayerBody->GetWorld()->DestroyBody(destroyPlayerBody);
        this->stopAllActions();
        switch (this->getToDestroyFlag()) {
            case ENEMY_DESTROY_DIE:
            {
                
                if(this->getBonusID() != 0)
                {
                    //初始化掉落拾取物的场景数据结构
                    BonusPrototypes *bonusPrototypes = BonusPrototypes::getInstance();
                    Bonus *bonus = bonusPrototypes->getBonusByID(this->getBonusID());
                    BonusSprite *bonusSprite = new BonusSprite();
                    bonusSprite->retain();
                    bonusSprite->init();
                    bonusSprite->setID(this->getBonusID());
                    bonusSprite->setPosition(this->getPosition());
                    bonusSprite->setVisible(true);
                    bonusSprite->setScale(0.5);
                    bonusSprite->initWithSpriteFrameName(bonus->getRes().c_str());
                    bonusSprite->setEntityType(BONUS);
                    bonusSprite->setRollingSpeed(bonus->getSpeed());
                    bonusSprite->setType(bonus->getType());
                    int bonusTag = m_playerFighter->bouns_BaseTag++;
                    bonusSprite->setTag(bonusTag);
                    batch->addChild(bonusSprite, BONUS_DEPTH, bonusTag);
                    
                    b2BodyDef bonusBodyDef;
                    bonusBodyDef.type = b2_dynamicBody;
                    bonusBodyDef.position = b2Vec2(this->getPosition().x/PTM_RATIO, this->getPosition().y/PTM_RATIO);
                    bonusBodyDef.bullet = false;
                    bonusBodyDef.userData = bonusSprite;
                    b2Body *bonusBody = getPhysicsBody()->GetWorld()->CreateBody(&bonusBodyDef);
                    CCSize bonusContentSize = bonusSprite->getContentSize();
                    b2PolygonShape bonusDynamicBox;
                    bonusDynamicBox.SetAsBox(bonusContentSize.width * 0.2 / PTM_RATIO, bonusContentSize.height * 0.2 / PTM_RATIO,b2Vec2(0, 0),0);
                    b2FixtureDef bonusFixtureDef;
                    bonusFixtureDef.shape = &bonusDynamicBox;
                    bonusFixtureDef.density = 0.0f;
                    bonusFixtureDef.friction = 0.0f;
                    bonusFixtureDef.filter.groupIndex = FILTER_BONUS_GROUPINDEX;
                    bonusFixtureDef.filter.categoryBits = FILTER_BONUS_CATEGORYBITS;
                    bonusFixtureDef.filter.maskBits = FILTER_BONUS_MASKBITS;
                    bonusBody->CreateFixture(&bonusFixtureDef);
                    bonusSprite->setPhysicsBody(bonusBody);
                    bonusSprite->getPhysicsBody()->SetActive(true); 
                }
                
                break;
            }
            case ENEMY_DESTROY_OUT:
            {
                break;
            }
            default:
                break;
        }
        batch->removeChild(this, true);
        if(this->getIsBoss() == 1)
        {
            CCNotificationCenter::sharedNotificationCenter()->postNotification(PAYOFF_SCENEN_NOTIFICATION, CCInteger::create(PAYOFF_PASS));
        }
        CCLog("enemy retaincount = %d",this->retainCount());
        delete this;
        return;
    }
    
    //发射敌机子弹
    CCDictElement *bulletElement= NULL;
    CCDICT_FOREACH(bulletDict, bulletElement)
    {
        int bulletID = bulletElement->getIntKey();
        Bullet *bulletDataInfo = (Bullet*)bulletElement->getObject();
        int beginFireFrameIdx = bulletDataInfo->getBegin();
        int group_num = bulletDataInfo->getGroup_num();
        int group_interval = bulletDataInfo->getGroup_interval();
        int frequency = bulletDataInfo->getFrequency();
        int currGroupNum = ((CCInteger*)bulletFireGroupNumDict->valueForKey(bulletID))->getValue();
        EnemyBulletSprite *newBulletSprite = NULL;
        if (m_iFrameIndex == beginFireFrameIdx && currGroupNum == group_num ) //到达子弹发射开始针时，发射第一个子弹
        {
            newBulletSprite = createEnemyBulletSprite(bulletID);
        }
        else if(m_iFrameIndex >  beginFireFrameIdx)
        {
            if (group_num == 0 || group_interval == 0 ) //不需要分组发射的逻辑
            {
                if((m_iFrameIndex-beginFireFrameIdx) % frequency == 0)
                {
                    newBulletSprite = createEnemyBulletSprite(bulletID);
                }
                
            }
            else //分组发射
            {
                if (currGroupNum == 0 && ((m_iFrameIndex-beginFireFrameIdx) % group_interval == 0)) { //分组发射时，组内的第一个子弹的发射
                    newBulletSprite = createEnemyBulletSprite(bulletID);
                    currGroupNum = group_num;
                }
                else if(currGroupNum > 0 && currGroupNum < group_num && ((m_iFrameIndex-beginFireFrameIdx) % frequency) == 0) //组内子弹的发射逻辑
                {
                   newBulletSprite = createEnemyBulletSprite(bulletID);
                }
            }
                
        }
        
        if(newBulletSprite != NULL)
        {
            batch->addChild(newBulletSprite, BULLET_DEPTH, newBulletSprite->getTag());
            currGroupNum = currGroupNum-1 < 0 ? 0 : currGroupNum-1;
            bulletFireGroupNumDict->setObject(CCInteger::create(currGroupNum), bulletID);
            int moveType = bulletDataInfo->getType();
            int speed = bulletDataInfo->getSpeed();
            float duration = bulletDataInfo->getDuration();
            float angle = bulletDataInfo->getAngle();
            int leftdisX = 0;
            int leftdisY = 0;
            switch (moveType)
            {
                case 1:
                {
                    float deltX = speed * sin(angle*PI/180);
                    float deltY = speed * cos(angle*PI/180);
                    CCActionInterval* actionBy = CCMoveBy::create(duration, CCPointMake(deltX,deltY));
                    newBulletSprite->runAction( CCRepeatForever::create(actionBy));
                    break;
                }
                    
                case 2:
                {
                    leftdisX = m_playerFighter->getPosition().x - getPosition().x;
                    leftdisY = m_playerFighter->getPosition().y - getPosition().y;
                    angle = atan(fabs((float)leftdisY)/fabs((float)leftdisX));
                    float speedX = 0.0f, speedY = 0.0f;
                    
                    speedX = speed * cos(angle);
                    speedY = speed * sin(angle);
                    
                    speedX = leftdisX > 0? speedX : -speedX;
                    speedY = leftdisY > 0? speedY : -speedY;
                    
                    CCActionInterval* actionBy = CCMoveBy::create(duration, CCPointMake(speedX,speedY));
                    newBulletSprite->runAction( CCRepeatForever::create(actionBy));
                    
                    break;
                }
                default:
                    break;
            }

            
        }
        
    }
    
  
    if(getColor().r != m_OldColor.r || getColor().g != m_OldColor.g || getColor().b != m_OldColor.b)
    {
        setColor(m_OldColor);
    }
}
